<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Complex ?</title>
        <style>
            body{
                background-color: black;
                width: 100vw;
                height: 100vh;
            }
            .main{
                width: 300px;
                height: 600px;
                margin: 2rem auto;
                border: 1px solid #888;
            }
            canvas{
                width: 100%;
                height: 100%;
            }
        </style>
    </head>

    <body>
        <div class="main">
            <canvas id="canvas" width="300" height="600"></canvas>
            <canvas id="refectCanvas" width="300" height="600" style="display: none;"></canvas>
            <canvas id="cacheCanvas" width="300" height="600" style="display: none;"></canvas>

            <button id="showRay">显示光线</button>
        </div>

        <script>
            const getRandomColor = () => {
                return [
                    Math.floor(Math.random() * 256),
                    Math.floor(Math.random() * 256),
                    Math.floor(Math.random() * 256),
                    1
                ];
            };

            const getRGBABrightness = (rgba) => {
                return (rgba[0] * 0.299 + rgba[1] * 0.587 + rgba[2] * 0.114) * rgba[3];
            };

            const adjustColorBrightness = (rgba, factor) => {
                return [
                    Math.min(255, Math.max(0, rgba[0] * factor)),
                    Math.min(255, Math.max(0, rgba[1] * factor)),
                    Math.min(255, Math.max(0, rgba[2] * factor)),
                    rgba[3]
                ];
            };

            const canvas = document.getElementById('canvas');
            const refectCanvas = document.getElementById('refectCanvas');
            const cacheCtx = document.getElementById('cacheCanvas').getContext('2d');
            const ctx = canvas.getContext('2d');
            const refectCtx = refectCanvas.getContext('2d');

            let time = 0;
            let showRay = false;

            // 上方方块
            let itemList = [];
            const itemSize = 20;
            for (let i = 0; i < itemSize; i++) {
                let color = getRandomColor();
                if (getRGBABrightness(color) < 0.5) {
                    adjustColorBrightness(color, 1.5);
                }
                itemList.push(color);
            }

            // 渲染上方方块动画
            const renderItem = ()=>{
                for (let i = 0; i < itemList.length; i++) {
                    const x = i * 120 - time * 2;
                    if (x < -100 || x > canvas.width) {
                        continue;
                    }
                    ctx.fillStyle = `rgba(${itemList[i][0]}, ${itemList[i][1]}, ${itemList[i][2]}, ${itemList[i][3]})`;
                    const radius = 15; // corner radius
                    ctx.beginPath();
                    ctx.moveTo(x + radius, 100);
                    ctx.lineTo(x + 80 - radius, 100);
                    ctx.arcTo(x + 80, 100, x + 80, 100 + radius, radius);
                    ctx.lineTo(x + 80, 100 + 200 - radius);
                    ctx.arcTo(x + 80, 100 + 200, x + 80 - radius, 100 + 200, radius);
                    ctx.lineTo(x + radius, 100 + 200);
                    ctx.arcTo(x, 100 + 200, x, 100 + 200 - radius, radius);
                    ctx.lineTo(x, 100 + radius);
                    ctx.arcTo(x, 100, x + radius, 100, radius);
                    ctx.fill();
                }
            }

            // 按钮位置大小
            const buttonX = canvas.width / 2;
            const buttonY = 400;
            const buttonR = 50;

            // 渲染按钮
            const renderButtonBase = () => {
                ctx.fillStyle = '#111';
                ctx.lineWidth = 2;
                ctx.strokeStyle = '#222';
                ctx.beginPath();
                ctx.arc(buttonX, buttonY, buttonR, 0, Math.PI * 2);
                // border
                ctx.stroke();
                ctx.fill();
            }


            const getImageDataColor = (imageData, x, y) => {
                const index = (y * imageData.width + x) * 4;
                return [
                    imageData.data[index],
                    imageData.data[index + 1],
                    imageData.data[index + 2],
                    imageData.data[index + 3] / 255
                ];
            };

            // 渲染按钮反射
            const renderButtonRefection = (imageData) => {
                refectCtx.clearRect(0, 0, refectCanvas.width, refectCanvas.height);

                const arcNumber = 360; // 弧分段
                const angleStep = (Math.PI * 2) / arcNumber;
                for (let i = 0; i < arcNumber; i++) {
                    const angle = i * angleStep;
                    const borderX = buttonX + (buttonR+3) * Math.cos(angle);
                    const borderY = buttonY + (buttonR+3) * Math.sin(angle);
                    let dd = 1; // 步进距离
                    let into = false;
                    const disLim = 120 // 最大追踪距离

                    while (dd < disLim) {
                        const x = Math.round(borderX + dd * Math.cos(angle));
                        const y = Math.round(borderY + dd * Math.sin(angle));
                        if (x < 0 || x >= imageData.width || y < 0 || y >= imageData.height) {
                            break;
                        }
                        const color = getImageDataColor(imageData, x, y);
                        if (getRGBABrightness(color) > 0.1) {
                            if (!into){ // 确保进入内部一点，而不是边界混合值
                                into = true;
                                dd += 1
                                continue
                            }
                            refectCtx.lineWidth = 1;
                            // 距离线性衰减亮度
                            const adjustedColor = adjustColorBrightness(color, (disLim-dd)/disLim*3);

                            refectCtx.strokeStyle = `rgba(${adjustedColor[0]}, ${adjustedColor[1]}, ${adjustedColor[2]}, ${adjustedColor[3]})`;
                            refectCtx.beginPath();
                            refectCtx.arc(buttonX, buttonY, buttonR-1, angle-angleStep/2, angle+angleStep/2);
                            refectCtx.stroke();

                            // debug
                            if (showRay){
                                refectCtx.beginPath();
                                refectCtx.moveTo(borderX, borderY);
                                refectCtx.lineTo(x, y);
                                refectCtx.stroke();
                            }

                            into = false
                            break; 

                        }
                        dd += 1; 
                    }
                }


                cacheCtx.clearRect(0, 0, canvas.width, canvas.height);33333333

                // 画到缓存
                cacheCtx.filter = 'none'; 
                cacheCtx.globalAlpha = 0.7;
                cacheCtx.drawImage(refectCanvas, 0, 0);

                // 添加模糊辉光效果
                cacheCtx.globalAlpha = 0.7;
                cacheCtx.filter = 'blur(2px) brightness(2)';
                cacheCtx.drawImage(refectCanvas, 0, 0);

                // 清楚内部
                cacheCtx.globalCompositeOperation = 'destination-out';
                cacheCtx.beginPath();
                cacheCtx.arc(buttonX, buttonY, buttonR-1, 0, Math.PI * 2);
                cacheCtx.fill();
                cacheCtx.globalCompositeOperation = 'source-over';

                ctx.drawImage(cacheCanvas, 0, 0);
            };


            const render = () => {
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                renderItem();
                renderButtonBase();

                const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
                renderButtonRefection(imageData);

                time += 1;
                if (time > itemSize * 120 / 2) {
                    time = 0;
                }
                requestAnimationFrame(render);
            };

            render();


            // showRay button
            document.getElementById('showRay').addEventListener('click', () => {
                showRay = !showRay;
                document.getElementById('showRay').innerText = showRay ? '隐藏光线' : '显示光线';
            });

        </script>
    </body>

</html>
